﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Slam;
using Microsoft.SharePoint;
using Slam.Configuration;
using Slam.Data;
using Slam.Logging;
using Slam.SharePoint;
using Slam.Events;
using System.Xml.Linq;
using System.Collections;
using SlamCms.SharePoint.Tagging.Data;
using SlamCms.SharePoint.Data;
using System.Web;
using System.Data.EntityClient;
using SlamCms.SharePoint.Core;

namespace SlamCms.SharePoint.SlamProfiles.Tags
{
	public class TagContentTypeItemCreator : ContentTypeItemCreator
	{
		private IConfigurationManager _configuration;
		private string _dataSchema;
		private ILogger _logger;

		private const string ModelName = "Data.SlamCms";

		#region Constructors

		public TagContentTypeItemCreator(IDataServices dataServices, IConfigurationManager configuration, ILogger logger)
			: base(dataServices, configuration, logger)
		{
			_configuration = configuration;
			_dataSchema = ((XmlSqlDataMapping)configuration.DataMapping).GetDataSchema();
			_logger = logger;
		}

		#endregion

		public override bool Create(SPListItem listItem)
		{
			bool createReturn = false;

			try
			{
				createReturn = base.Create(listItem);

				if (createReturn && HttpContext.Current != null)
				{
					int parentPositionId = 0;
					string tagCategoryId = "";
					string tagTreeId = "";
					if (HttpContext.Current.Request.QueryString["parent"] != null)
					{
						Int32.TryParse(HttpContext.Current.Request.QueryString["parent"], out parentPositionId);
					}

					if (HttpContext.Current.Request.QueryString["category"] != null)
					{
						tagCategoryId = HttpContext.Current.Request.QueryString["category"];
					}

					if (HttpContext.Current.Request.QueryString["tree"] != null)
					{
						tagTreeId = HttpContext.Current.Request.QueryString["tree"];
					}

					if (!String.IsNullOrEmpty(tagCategoryId))
					{
						string connectionString = "";
						DataMapping currentDataMapping = _configuration.DataMapping;
						string siteCollection = SPContext.GetContext(HttpContext.Current).Site.ServerRelativeUrl.TrimStart('/');
						if (!String.IsNullOrEmpty(siteCollection) && _configuration.DataMappings.ContainsKey(siteCollection))
						{
							currentDataMapping = _configuration.DataMappings[siteCollection];
						}
						if (_configuration is XmlConfigurationManager)
						{
							_dataSchema = ((XmlSqlDataMapping)currentDataMapping).GetDataSchema();
							connectionString = ((XmlSqlDataMapping)currentDataMapping).GetConnectionString();
						}

						if (String.IsNullOrEmpty(connectionString))
						{
							connectionString = _configuration.GetSection<ConnectionStringSection>("ConnectionStrings").Default;
						}
						else
						{
							connectionString = _configuration.GetSection<ConnectionStringSection>("ConnectionStrings").GetConnectionString(connectionString);
						}

						EntityConnectionStringBuilder entityConnection = new EntityConnectionStringBuilder();
						entityConnection.Provider = "System.Data.SqlClient";
						if (!connectionString.Contains("Persist Security Info"))
						{
							connectionString = connectionString.TrimEnd(';') + ";Persist Security Info=True;";
						}
						entityConnection.ProviderConnectionString = connectionString;
						entityConnection.Metadata = String.Format("res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl", ModelName);

						connectionString = entityConnection.ToString();

						Entities context = new Entities(connectionString);
						context.SetStoreSchema(ModelName, _dataSchema);

						string tagId = Convert.ToString(listItem.GetUniqueId());
						Tag matchedTag = context.Tags.Where(t => t.TagID.Equals(tagId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
						TagCategory matchedTagCategory = context.TagCategories.Where(tc => tc.TagCategoryID.Equals(tagCategoryId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
						TagTree matchedTagTree = context.TagTrees.Where(tt => tt.TagTreeID.Equals(tagTreeId, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

						if (matchedTag != null && !String.IsNullOrEmpty(matchedTag.TagID) && matchedTagTree != null)
						{
							bool reorderedPositions = false;
							TagHierarchyPosition position = new TagHierarchyPosition();
							position.ParentPositionID = parentPositionId > 0 ? parentPositionId : (int?)null;
							position.Tag = matchedTag;
							position.TagCategory = matchedTagCategory;
							position.TagTree = matchedTagTree;
							//If this new position has a parent, push all positions
							//past this parent down, and set SortOrder to the parent's
							//current SortOrder value.  Otherwise set SorOrder to 0.
							if (parentPositionId > 0)
							{
								TagHierarchyPosition matchedParentPosition = context.TagHierarchyPositions.Where(p => p.PositionID == parentPositionId).FirstOrDefault();
								if (matchedParentPosition != null && matchedParentPosition.PositionID > 0)
								{
									position.SortOrder = matchedParentPosition.SortOrder + 1;

									var hierarchyPositions = (from hierarchyPosition in context.TagHierarchyPositions
															  where hierarchyPosition.TagTree.TagTreeID == tagTreeId &&
																	hierarchyPosition.SortOrder > matchedParentPosition.SortOrder
															  orderby hierarchyPosition.SortOrder
															  select hierarchyPosition);

									foreach (var hierarchyPosition in hierarchyPositions)
									{
										hierarchyPosition.SortOrder = hierarchyPosition.SortOrder + 1;
									}
									reorderedPositions = true;
								}
							}
							else
							{
								position.SortOrder = 0;
							}
							context.AddToTagHierarchyPositions(position);
							context.SaveChanges(true);

							//If new position is top level then reorder all positions
							if (!reorderedPositions)
							{
								var hierarchyPositions = (from hierarchyPosition in context.TagHierarchyPositions.Include("TagCategory")
														  orderby hierarchyPosition.TagCategory.DisplayOrder, hierarchyPosition.SortOrder
														  where hierarchyPosition.TagTree.TagTreeID == tagTreeId
														  select hierarchyPosition);

								int i = 1;
								foreach (var hierarchyPosition in hierarchyPositions)
								{
									hierarchyPosition.SortOrder = i;
									i++;
								}

								context.SaveChanges(true);
							}

							SlamCmsContext.Data.Cache.InvalidateTags();
						}
					}
				}
			}
			catch (Exception ex)
			{
				_logger.LogMessage("Exception", ex.ToString());
			}

			return createReturn;
		}
	}
}
